﻿package com.singlenotion.transitions{

	import flash.display.Sprite;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.utils.setTimeout;
	import gs.easing.Quad;
	import gs.TweenLite;

	public class MaskTransitions extends Sprite 
	{	
		public static const TRANSITION_COMPLETE:String = "transitionComplete";
		public static const TRANSITION_IN:String = "in";
		public static const TRANSITION_OUT:String = "out";
		public static const ORDER_RANDOM:String = "random";
		public static const ORDER_FOLLOW:String = "follow";
		
		private var _transitionMask:Sprite = new Sprite();
		private var _column:int = 0;
		private var _row:int = 0;
		private var _delay:Number = 0;
		private var _maskList:Array = new Array();

		public function MaskTransitions():void 
		{
			addChild(_transitionMask);
		}
		
		private function removeMask():void 
		{
			if (_maskList.length != 0) {
				var i:int;
				var l:int = _maskList.length;
				for (i = 0; i < l; i++) {
					_transitionMask.removeChild(_maskList[i]);
				}
				_maskList.length = 0;
			}
		}
		
		private function createBlock($w:int, $h:int):Sprite 
		{	
			var block:Sprite = new Sprite();
			
			block.graphics.clear();
			block.graphics.beginFill(0x000000, 1);
			block.graphics.drawRect(0, 0, $w, $h);
			
			_transitionMask.addChild(block);
			_maskList.push(block);
			
			return block;
		}
		
		public function blockTransition($image:DisplayObject, $blockSize:int, $direction:String, $rotate:Boolean, $order:String = "", $effectSpeed:Number = 1, $blockSpeed:Number = 0.5):void 
		{
			_row = 0;
			_column = 0;
			
			removeMask();
			
			var totalBlocks:int = Math.ceil($image.width / $blockSize) * Math.ceil($image.height / $blockSize);
			var totalTime:Number = 0;
			
			var i:int;
			for (i = 0; i<totalBlocks; i++) {
				
				switch ($order) {
					case "":
						_delay = 0;
						break;
					case MaskTransitions.ORDER_RANDOM:
						_delay = Math.random() * $effectSpeed;
						break;
					case MaskTransitions.ORDER_FOLLOW:
						_delay = i * $effectSpeed;
						break;
				}
				
				if (_delay > totalTime) totalTime = _delay;
				
				var block:Sprite = createBlock($blockSize, $blockSize);
				
				if (i % Math.ceil($image.width / $blockSize) == 0) {
					_column = 0;
					_row++;
				}
				
				block.x = _column * $blockSize;
				block.y = (_row * $blockSize) - $blockSize;
				
				_column++;
				
				_transitionMask.x = $image.x;
				_transitionMask.y = $image.y;
				
				if ($direction == MaskTransitions.TRANSITION_IN) {
					block.scaleX = block.scaleY = 0;
					TweenLite.to(block, $blockSpeed, { scaleX:1, scaleY:1, ease:Quad.easeInOut, delay:_delay } );
				} else {
					block.scaleX = block.scaleY = 1;
					TweenLite.to(block, $blockSpeed, { scaleX:0, scaleY:0, ease:Quad.easeInOut, delay:_delay } );
				}
				
				if ($rotate) TweenLite.to(block, $blockSpeed, { rotation:360, ease:Quad.easeInOut, delay:_delay } );
			}
			
			$image.mask = _transitionMask;
			
			setTimeout(dispatchFinish, (totalTime + $blockSpeed) * 1001);
		}
		
		private function dispatchFinish():void
		{
			dispatchEvent(new Event(MaskTransitions.TRANSITION_COMPLETE, true, true));
		}
	}
}